package moe.rename;

import java.io.File;
import java.io.FilenameFilter;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import javax.swing.JFileChooser;

import moe.dao.BaseDao;
import moe.dao.PostDao;
import moe.entity.Post;

public abstract class BaseRename implements FilenameFilter {
	private PostDao postDao;
	private Pattern pattern;

	protected Map<String, String> escapeMap;

	BaseRename(Pattern pattern) {
		this.pattern = pattern;

		postDao = new PostDao(BaseDao.ConnType.DEFAULT);
		initEscapeMap();
	}

	private void initEscapeMap() {
		escapeMap = new HashMap<String, String>();
		escapeMap.put("\\\\", "%5C");
		escapeMap.put("/", "%2F");
		escapeMap.put(":", "%3A");
		escapeMap.put("\\?", "%3F");
		escapeMap.put("\\*", "%2A");
		escapeMap.put("\"", "%22");
		escapeMap.put("<", "%3C");
		escapeMap.put(">", "%3E");
		escapeMap.put("\\|", "%7C");
	}

	private boolean doRename(File file, String targetDir) {
		long id = getId(file.getName());
		Post post = getPost(Long.valueOf(id));
		if (post == null) {
			System.err.println("WARNING! Can't find post(id:" + id + ") from DataBase! \""
					+ file.getPath() + "\" rename failed.");
			return false;
		}
		String newFileName = getNewFileName(file.getName(), post);
		if (!targetDir.endsWith(File.separator)) {
			targetDir += File.separator;
		}
		File newFile = new File(targetDir + newFileName);
		if (newFile.exists()) {
			System.err.println("WARNING! File \"" + newFile.getPath() + "\" already exist! \""
					+ file.getPath() + "\" rename failed.");
			return false;
		}
		// System.out.println(newFile.getPath());

		if (!file.renameTo(newFile)) {
			System.err.println("WARNING! File \"" + file.getPath() + "\" rename to \""
					+ newFile.getPath() + "\" failed.");
			return false;
		}
		return true;
	}

	private Post getPost(long id) {
		return postDao.getPost(id);
	}

	private void checkParam(String srcDir, String targetDir) {
		File src = new File(srcDir);
		File target = new File(targetDir);
		if (!src.exists()) {
			throw new RuntimeException("Directory \"" + srcDir + "\" not found");
		}
		if (!src.isDirectory()) {
			throw new RuntimeException("Path \"" + srcDir + "\" is not a directory");
		}
		if (!target.exists()) {
			target.mkdirs();
		}
		if (!target.isDirectory()) {
			throw new RuntimeException("Path \"" + targetDir + "\" is not a directory");
		}
	}

	private String selectDirectory(String title) {
		JFileChooser chooser = new JFileChooser(System.getProperty("user.dir"));
		chooser.setDialogTitle(title);
		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		int returnVal = chooser.showDialog(null, "Select");
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			String path = chooser.getSelectedFile().getPath();
			System.out.println(title + ": " + path);
			return path;
		}
		return null;
	}

	public void execute() {
		String srcDir = selectDirectory("Select input directory");
		String targetDir = selectDirectory("Select output directory");
		checkParam(srcDir, targetDir);
		System.out.println("Renaming...");
		File src = new File(srcDir);
		File[] files = src.listFiles(this);
		int success = 0, fail = 0;
		for (File file : files) {
			if (doRename(file, targetDir)) {
				success++;
			} else {
				fail++;
			}
			// System.out.println(file.getName());
		}
		System.out.println("Report: total:" + files.length + " successes:" + success + " failures:"
				+ fail);
	}

	public boolean accept(File dir, String name) {
		if (pattern.matcher(name).matches()) {
			return true;
		}
		return false;
	}

	protected boolean isWindows() {
		String osName = System.getProperty("os.name");
		if (osName.contains("Windows")) {
			return true;
		}
		return false;
	}

	protected abstract long getId(String fileName);

	protected abstract String getNewFileName(String srcFileName, Post post);
}
